package com.lzhl.buildjar.ui.support;

import java.io.File;
import java.util.*;

/**
 * @author 李柱良(@柱子的日月)
 * @date 2016/5/10
 */
public class AutoFill {
    private File classpath = null;
    private String packageName = "";
    private String className = "";
    private int lastDay = 1;
    private int classCount = 0;
    private boolean includeInner = true;

    private Set<String> packageNames = new HashSet<String>();
    private Set<String> classNames = new HashSet<String>();
    private long time_req = 0;

    private List<File> files = null;
    private int buffer_size = 0;
    private long time_min = 0;

    public AutoFill(File classpath, String packageName,
                    String className, int lastDay, int classCount, boolean includeInner) {
        this.classpath = classpath;
        setPackageName(packageName);
        setClassName(className);
        setLastDay(lastDay);
        setClassCount(classCount);
        this.includeInner = includeInner;

        clear();
    }

    public void clear() {
        if(classCount > 0) {
            files = new ArrayList<File>(buffer_size);
        }
        else {
            files = new LinkedList<File>();
        }
        time_min = 0;
    }

    public void addFile(File file, String packageName) {
        if(!filter(file, packageName)) {
            return;
        }

        if(classCount > 0) {
            if(file.lastModified() > time_min) {
                files.add(file);
                if(files.size() >= buffer_size) {
                    count();
                }
            }
        }
        else {
            files.add(file);
        }
    }

    public void count() {
        if(classCount > 0) {
            sort(files);
            for(int i = files.size() - 1; i >= classCount; i--) {
                files.remove(i);
            }
            time_min = files.get(files.size() - 1).lastModified();
        }
    }

    public boolean filter(File file, String packageName) {
        if(time_req > 0) {
            if(file.lastModified() < time_req) {
                return false;
            }
        }

        if(packageNames.size() > 0) {
            boolean found = false;
            for(String str : packageNames) {
                if(packageName.contains(str)) {
                    found = true;
                    break;
                }
            }
            if(!found) {
                return false;
            }
        }

        String name = file.getName().toLowerCase();
        if(classNames.size() > 0) {
            boolean found = false;
            for(String str : classNames) {
                if(name.contains(str)) {
                    found = true;
                    break;
                }
            }
            if(!found) {
                return false;
            }
        }

        if(!includeInner) {
            if(name.endsWith(".class") && name.contains("$")) {
                return false;
            }
        }

        return true;
    }

    private void sort(List<File> files) {
        Collections.sort(files, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                return longcompare(o2.lastModified(), o1.lastModified());
            }
        });
    }

    public static int longcompare(long x, long y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

    public File getClasspath() {
        return classpath;
    }

    public void setClasspath(File classpath) {
        this.classpath = classpath;
    }

    public String getPackageName() {
        return packageName;
    }

    public void setPackageName(String packageName) {
        if(packageName == null) {
            packageName = "";
        }
        this.packageName = packageName;

        this.packageNames = new HashSet<String>();
        String[] strs = packageName.split(":");
        for (String str : strs) {
            if(str.trim().length() > 0) {
                this.packageNames.add(str.trim().toLowerCase());
            }
        }
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        if(className == null) {
            className = "";
        }
        this.className = className;

        this.classNames = new HashSet<String>();
        String[] strs = className.split(":");
        for (String str : strs) {
            if(str.trim().length() > 0) {
                this.classNames.add(str.trim().toLowerCase());
            }
        }
    }

    public int getLastDay() {
        return lastDay;
    }

    public void setLastDay(int lastDay) {
        if(lastDay < 0) {
            lastDay = 0;
        }
        this.lastDay = lastDay;
        this.time_req = 0;
        if(lastDay > 0) {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            if(lastDay != 1) {
                calendar.add(Calendar.DAY_OF_MONTH, 1-lastDay);
            }

//        Date date = calendar.getTime();
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//        String s = sdf.format(date);

            this.time_req = calendar.getTimeInMillis();
        }
    }

    public int getClassCount() {
        return classCount;
    }

    public void setClassCount(int classCount) {
        if(classCount < 0) {
            classCount = 0;
        }
        this.classCount = classCount;
        if(classCount > 0) {
            buffer_size = classCount * 2;
            if(buffer_size < 200) {
                buffer_size = 200;
            }
        }
    }

    public boolean isIncludeInner() {
        return includeInner;
    }

    public void setIncludeInner(boolean includeInner) {
        this.includeInner = includeInner;
    }

    public List<File> getFiles() {
        return files;
    }

}
